/*
* Copyright 2014 Bevbot LLC <info@bevbot.com>
*
* This file is part of the Kegtab package from the Kegbot project. For
* more information on Kegtab or Kegbot, see <http://kegbot.org/>.
*
* Kegtab is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
* Kegtab is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with Kegtab. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kegbot.api;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Message.Builder;
import org.codehaus.jackson.JsonNode;
import java.io.IOException;
import java.util.Iterator;
public class ProtoEncoder {
/**
* Assigns all fields in {@link JsonNode} instance to a {@link Builder}.
*
* @param builder the builder to be populated
* @param root the JSON object
* @return the original builder, populated with any fields that were discovered
*/
public static Builder toProto(final Builder builder, final JsonNode root) {
Descriptor type = builder.getDescriptorForType();
for (final FieldDescriptor fieldDesc : type.getFields()) {
final String attrName = fieldDesc.getName();
final JsonNode node = root.get(attrName);
if (node == null) {
continue;
}
if (node.isNull()) {
continue;
}
if (fieldDesc.isRepeated()) {
final Iterator<JsonNode> iter = node.getElements();
while (iter.hasNext()) {
builder.addRepeatedField(fieldDesc, toJavaObj(builder, fieldDesc, iter.next()));
}
} else {
builder.setField(fieldDesc, toJavaObj(builder, fieldDesc, node));
}
}
return builder;
}
private static Object toJavaObj(final Builder builder, final FieldDescriptor fieldDesc,
final JsonNode node) {
Object value;
switch (fieldDesc.getJavaType()) {
case MESSAGE:
final Builder subBuilder = builder.newBuilderForField(fieldDesc);
value = toProto(subBuilder, node).build();
break;
case BOOLEAN:
value = Boolean.valueOf(node.getBooleanValue());
break;
case BYTE_STRING:
try {
value = node.getBinaryValue();
} catch (IOException e) {
throw new RuntimeException(e);
}
break;
case DOUBLE:
value = Double.valueOf(node.getDoubleValue());
break;
case FLOAT:
value = Float.valueOf(Double.valueOf(node.getDoubleValue()).floatValue());
break;
case ENUM:
value = fieldDesc.getEnumType().findValueByName(node.getTextValue());
break;
case INT:
value = Integer.valueOf(node.getIntValue());
break;
case LONG:
value = Long.valueOf(node.getLongValue());
break;
case STRING:
value = node.getTextValue();
break;
default:
throw new IllegalArgumentException();
}
return value;
}
}